﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using Microsoft.Research.DynamicDataDisplay; // Core functionality
using Microsoft.Research.DynamicDataDisplay.DataSources; // EnumerableDataSource
using Microsoft.Research.DynamicDataDisplay.PointMarkers; // CirclePointMarker
using Microsoft.Research.DynamicDataDisplay.Charts.Navigation;
using Microsoft.Research.DynamicDataDisplay.ViewportRestrictions;
using NutriStat;

namespace NutriChart
{
    /// <summary>
    /// Interaction logic for ChartWindow.xaml
    /// </summary>
    public partial class ChartWindow : Window
    {        
        private List<LineAndMarker<MarkerPointsGraph>> chart;
        private List<IPointDataSource> ds;
        private string patientName;
        private string gender;
        private string measurement;
        private string reference;
        private string type;
        private NutriConfig config;
        private bool metric;

        #region Constructors
        public ChartWindow()
        {
            InitializeComponent();

            PatientName = "No name";
            Gender = "Male";
            Measurement = "BMI";
            Reference = "CDC";
            Type = "C";
            Metric = true;

            ds = new List<IPointDataSource>();
            chart = new List<LineAndMarker<MarkerPointsGraph>>();

            Loaded += new RoutedEventHandler(ChartWindow_Loaded);
        }
        #endregion Constructors        

        #region Properties
        /// <summary>
        /// Gets/sets the Name property
        /// </summary>
        private string PatientName
        {
            get 
            {
                return patientName;
            }
            set
            {
                patientName = value;
            }
        }

        /// <summary>
        /// Gets/sets whether the units are in metric or English.
        /// </summary>
        private bool Metric
        {
            get
            {
                return metric;
            }
            set
            {
                metric = value;
            }
        }

        /// <summary>
        /// Gets/sets the Name property
        /// </summary>
        private string Gender
        {
            get
            {
                return gender;
            }
            set
            {
                gender = value;
            }
        }

        /// <summary>
        /// Gets/sets the Measurement property
        /// </summary>
        private string Measurement
        {
            get
            {
                return measurement;
            }
            set
            {
                measurement = value;
            }
        }

        /// <summary>
        /// Gets/sets the Reference property
        /// </summary>
        private string Reference
        {
            get
            {
                return reference;
            }
            set
            {
                reference = value;
            }
        }

        /// <summary>
        /// Gets/sets the Measurement property
        /// </summary>
        private string Type
        {
            get
            {
                return type;
            }
            set
            {
                type = value;                
            }
        }
        #endregion Properties

        #region Events
        private void Button_Click(object sender, RoutedEventArgs e)
        {
            for (int i = 0; i < chart.Count; i++)
            {
                if (chart[i].MarkerGraph.DataSource != null)
                {
                    chart[i].MarkerGraph.DataSource = null;
                }
                else
                {
                    chart[i].MarkerGraph.DataSource = ds[i];
                }
            }
        }        

        private void ChartWindow_Loaded(object sender, RoutedEventArgs e)
        {
            try
            {
                config = new NutriConfig();
                NutriConfig.SetCurrentDirectory(Directory.GetCurrentDirectory());
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }


            try
            {                
                string[] args = Environment.GetCommandLineArgs();                
                List<double> age = new List<double>();
                List<double> measure = new List<double>();
                List<double> score = new List<double>();

                // Put our x/y values into our List<>
                if (args.Length > 8)
                {
                    for (int i = 6; i < args.Length; i = i + 3)
                    {
                        age.Add(Convert.ToDouble(args[i]));
                    }

                    for (int i = 7; i < args.Length; i = i + 3)
                    {
                        measure.Add(Convert.ToDouble(args[i]));
                    }

                    for (int i = 8; i < args.Length; i = i + 3)
                    {
                        score.Add(Convert.ToDouble(args[i]));
                    }

                    PatientName = args[1];
                    Gender = args[2];
                    Measurement = args[3];
                    Reference = args[4];
                    Type = args[5];
                }
                else
                {
                    MessageBox.Show("No data points found for this measurement.");
                    this.Close();
                    return;
                }

                double xAxisModifier = 1;
                double yAxisModifier = 1;
                string yAxisName = "Body mass index";
                string xAxisName = "Age (months)";
                string fullMeasurementName = "Body mass index-for-age";                
                if(Measurement.Equals(MeasurementOptions.BMI.Abbreviation))
                {
                    fullMeasurementName = MeasurementOptions.BMI.FullName;
                    yAxisName = "Body mass index";
                }

                else if (Measurement.Equals(MeasurementOptions.WH.Abbreviation))
                {
                    fullMeasurementName = MeasurementOptions.WH.FullName;
                    yAxisName = "Weight";
                    xAxisName = "Height";
                    if (config.UnitsWeight.Equals(MeasurementUnits.Pound.Abbreviation))
                    {
                        Metric = false;
                        yAxisName = yAxisName + " (" + MeasurementUnits.Pound.Abbreviation + ")";
                        xAxisName = xAxisName + " (" + MeasurementUnits.Inch.Abbreviation + ")";
                        yAxisModifier = MeasurementUnits.Kilogram.ToPounds();
                        xAxisModifier = MeasurementUnits.Centimeter.ToInches();
                    }
                    else
                    {
                        yAxisName = yAxisName + " (" + MeasurementUnits.Kilogram.Abbreviation + ")";
                        xAxisName = xAxisName + " (" + MeasurementUnits.Centimeter.Abbreviation + ")";
                    }
                }

                else if (Measurement.Equals(MeasurementOptions.WL.Abbreviation))
                {
                    fullMeasurementName = MeasurementOptions.WL.FullName;
                    yAxisName = "Weight";
                    xAxisName = "Length";
                    if (config.UnitsWeight.Equals(MeasurementUnits.Pound.Abbreviation))
                    {
                        yAxisName = yAxisName + " (" + MeasurementUnits.Pound.Abbreviation + ")";
                        xAxisName = xAxisName + " (" + MeasurementUnits.Inch.Abbreviation + ")";
                        yAxisModifier = MeasurementUnits.Kilogram.ToPounds();
                        xAxisModifier = MeasurementUnits.Centimeter.ToInches();
                        Metric = false;
                    }
                    else
                    {
                        yAxisName = yAxisName + " (" + MeasurementUnits.Kilogram.Abbreviation + ")";
                        xAxisName = xAxisName + " (" + MeasurementUnits.Centimeter.Abbreviation + ")";                        
                    }
                }

                else if (Measurement.Equals(MeasurementOptions.WA.Abbreviation))
                {
                    fullMeasurementName = MeasurementOptions.WA.FullName;
                    yAxisName = "Weight";
                    if (config.UnitsWeight.Equals(MeasurementUnits.Pound.Abbreviation))
                    {
                        yAxisName = yAxisName + " (" + MeasurementUnits.Pound.Abbreviation + ")";
                        yAxisModifier = MeasurementUnits.Kilogram.ToPounds();
                        Metric = false;
                    }
                    else
                    {
                        yAxisName = yAxisName + " (" + MeasurementUnits.Kilogram.Abbreviation + ")";
                    }
                }

                else if (Measurement.Equals(MeasurementOptions.HA.Abbreviation))
                {
                    fullMeasurementName = MeasurementOptions.HA.FullName;
                    yAxisName = "Height";
                    if (config.UnitsHeight.Equals(MeasurementUnits.Inch.Abbreviation))
                    {
                        yAxisName = yAxisName + " (" + MeasurementUnits.Inch.Abbreviation + ")";
                        yAxisModifier = MeasurementUnits.Centimeter.ToInches();
                        Metric = false;
                    }
                    else
                    {
                        yAxisName = yAxisName + " (" + MeasurementUnits.Centimeter.Abbreviation + ")";
                    }
                }

                else if (Measurement.Equals(MeasurementOptions.LA.Abbreviation))
                {
                    fullMeasurementName = MeasurementOptions.LA.FullName;
                    yAxisName = "Length";
                    if (config.UnitsHeight.Equals(MeasurementUnits.Inch.Abbreviation))
                    {
                        yAxisName = yAxisName + " (" + MeasurementUnits.Inch.Abbreviation + ")";
                        yAxisModifier = MeasurementUnits.Centimeter.ToInches();
                        Metric = false;
                    }
                    else
                    {
                        yAxisName = yAxisName + " (" + MeasurementUnits.Centimeter.Abbreviation + ")";
                    }
                }

                else if (Measurement.Equals(MeasurementOptions.HCA.Abbreviation))
                {
                    fullMeasurementName = MeasurementOptions.HCA.FullName;
                    yAxisName = "Head circumference";
                    if (config.UnitsHead.Equals(MeasurementUnits.Inch.Abbreviation))
                    {
                        yAxisName = yAxisName + " (" + MeasurementUnits.Inch.Abbreviation + ")";
                        yAxisModifier = MeasurementUnits.Centimeter.ToInches();
                        Metric = false;
                    }
                    else
                    {
                        yAxisName = yAxisName + " (" + MeasurementUnits.Centimeter.Abbreviation + ")";
                    }
                }

                else if (Measurement.Equals(MeasurementOptions.MUACA.Abbreviation))
                {
                    fullMeasurementName = MeasurementOptions.MUACA.FullName;
                    yAxisName = "Mid-upper arm circumference";
                    if (config.UnitsSkin.Equals(MeasurementUnits.Inch.Abbreviation))
                    {
                        yAxisName = yAxisName + " (" + MeasurementUnits.Inch.Abbreviation + ")";
                        yAxisModifier = MeasurementUnits.Centimeter.ToInches();
                        Metric = false;
                    }
                    else
                    {
                        yAxisName = yAxisName + " (" + MeasurementUnits.Centimeter.Abbreviation + ")";
                    }
                }

                else if (Measurement.Equals(MeasurementOptions.SSFA.Abbreviation))
                {
                    fullMeasurementName = MeasurementOptions.SSFA.FullName;
                    yAxisName = "Subscapular skin fold";
                    if (config.UnitsSkin.Equals(MeasurementUnits.Inch.Abbreviation))
                    {
                        yAxisName = yAxisName + " (" + MeasurementUnits.Inch.Abbreviation + ")";
                        yAxisModifier = MeasurementUnits.Millimeter.ToInches();
                        Metric = false;
                    }
                    else
                    {
                        yAxisName = yAxisName + " (" + MeasurementUnits.Millimeter.Abbreviation + ")";
                    }
                }

                else if (Measurement.Equals(MeasurementOptions.TSFA.Abbreviation))
                {
                    fullMeasurementName = MeasurementOptions.TSFA.FullName;
                    yAxisName = "Triceps skin fold";
                    if (config.UnitsArm.Equals(MeasurementUnits.Inch.Abbreviation))
                    {
                        yAxisName = yAxisName + " (" + MeasurementUnits.Inch.Abbreviation + ")";
                        yAxisModifier = MeasurementUnits.Millimeter.ToInches();
                        Metric = false;
                    }
                    else
                    {
                        yAxisName = yAxisName + " (" + MeasurementUnits.Millimeter.Abbreviation + ")";
                    }
                }

                if (!Metric)
                {
                    for (int i = 0; i < measure.Count; i++)
                    {
                        measure[i] = measure[i] * yAxisModifier;
                        age[i] = age[i] * xAxisModifier;
                    }
                }

                if (Type.Equals("C"))
                {
                    Type = "percentiles";                 
                }
                else if (Type.Equals("Z"))
                {
                    Type = "z-scores";                    
                }
                else if (Type.Equals("N"))
                {
                    Type = "normal curve";
                    yAxisName = "% of children";
                    xAxisName = "Z-score";
                }

                string title = Reference;
                if (Reference.Equals("CDC"))
                {
                    title = title + " 2000";
                }
                title = title + " " + fullMeasurementName + " " + Type + " (" + Gender + "s)";
                

                // Set window title
                //this.Title = Reference + " " + Measurement + " " + Type;
                this.Title = title;                

                ChartTitle.Content = title;
                if (Type.Equals("N"))
                {
                    ChartSubTitle.Content = PatientName;
                }
                else
                {
                    ChartSubTitle.Content = "Patient: " + PatientName;
                }
                yAxisTitle.Content = yAxisName;
                xAxisTitle.Content = xAxisName;


                if (Type.Equals("percentiles"))
                {
                    PlotPercentiles(measure, age, score);
                }
                else if (Type.Equals("z-scores"))
                {
                    PlotZScores(measure, age);
                }
                else
                {
                    //PlotNormalCurve(score);
                }

                
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }

        } // ChartWindow_Loaded()
        #endregion Events

        #region Methods
        private Color GetColorFromConfig(string rgb)
        {
            #region Input Validation
            if (rgb.Length > 11 || rgb.Length < 5)
            {                
                // TODO: error!
                return Color.FromRgb(0, 0, 0);
            }
            #endregion Input Validation
            string[] pieces = rgb.Split(',');

            byte r = Byte.Parse(pieces[0]);
            byte g = Byte.Parse(pieces[1]);
            byte b = Byte.Parse(pieces[2]);

            return Color.FromRgb(r, g, b);
        }

        private void PlotPercentiles(List<double> measure, List<double> age, List<double> score)
        {
            try
            {
                // Set file name to pull growth curves from
                string fileName = "Resources\\" + Reference + Measurement + "_" + Gender + ".csv";

                // load growth curves from the appropriate file
                List<GrowthCurvesPercentiles> percentilesList = LoadGrowthCurvesPercentiles(fileName, Measurement, Metric);

                double[] C1 = new double[percentilesList.Count];
                double[] C3 = new double[percentilesList.Count];
                double[] C5 = new double[percentilesList.Count];
                double[] C10 = new double[percentilesList.Count];
                double[] C15 = new double[percentilesList.Count];
                double[] C25 = new double[percentilesList.Count];
                double[] C50 = new double[percentilesList.Count];
                double[] C75 = new double[percentilesList.Count];
                double[] C85 = new double[percentilesList.Count];
                double[] C90 = new double[percentilesList.Count];
                double[] C95 = new double[percentilesList.Count];
                double[] C97 = new double[percentilesList.Count];
                double[] C99 = new double[percentilesList.Count];
                double[] ages = new double[percentilesList.Count];

                for (int i = 0; i < percentilesList.Count; ++i)
                {
                    C1[i] = percentilesList[i].C1;
                    C3[i] = percentilesList[i].C3;
                    C5[i] = percentilesList[i].C5;
                    C10[i] = percentilesList[i].C10;
                    C15[i] = percentilesList[i].C15;
                    C25[i] = percentilesList[i].C25;
                    C50[i] = percentilesList[i].C50;
                    C75[i] = percentilesList[i].C75;
                    C85[i] = percentilesList[i].C85;
                    C90[i] = percentilesList[i].C90;
                    C95[i] = percentilesList[i].C95;
                    C97[i] = percentilesList[i].C97;
                    C99[i] = percentilesList[i].C99;
                    ages[i] = percentilesList[i].xaxis;
                }

                var C1DataSource = new EnumerableDataSource<double>(C1);
                C1DataSource.SetYMapping(y => y);

                var C3DataSource = new EnumerableDataSource<double>(C3);
                C3DataSource.SetYMapping(y => y);

                var C5DataSource = new EnumerableDataSource<double>(C5);
                C5DataSource.SetYMapping(y => y);

                var C10DataSource = new EnumerableDataSource<double>(C10);
                C10DataSource.SetYMapping(y => y);

                var C15DataSource = new EnumerableDataSource<double>(C15);
                C15DataSource.SetYMapping(y => y);

                var C25DataSource = new EnumerableDataSource<double>(C25);
                C25DataSource.SetYMapping(y => y);

                var C50DataSource = new EnumerableDataSource<double>(C50);
                C50DataSource.SetYMapping(y => y);

                var C75DataSource = new EnumerableDataSource<double>(C75);
                C75DataSource.SetYMapping(y => y);

                var C85DataSource = new EnumerableDataSource<double>(C85);
                C85DataSource.SetYMapping(y => y);

                var C90DataSource = new EnumerableDataSource<double>(C90);
                C90DataSource.SetYMapping(y => y);

                var C95DataSource = new EnumerableDataSource<double>(C95);
                C95DataSource.SetYMapping(y => y);

                var C97DataSource = new EnumerableDataSource<double>(C97);
                C97DataSource.SetYMapping(y => y);

                var C99DataSource = new EnumerableDataSource<double>(C99);
                C99DataSource.SetYMapping(y => y);

                var ageDataSource = new EnumerableDataSource<double>(ages);
                ageDataSource.SetXMapping(x => x);

                var ageMeasurementDataSource = new EnumerableDataSource<double>(age);
                ageMeasurementDataSource.SetXMapping(x => x);

                var scoreDataSource = new EnumerableDataSource<double>(score);
                //scoreDataSource.SetXYMapping(

                var measureDataSource = new EnumerableDataSource<double>(measure);
                measureDataSource.SetYMapping(y => y);

                CompositeDataSource compositeDataSource0 = new
                  CompositeDataSource(ageDataSource, C1DataSource);
                CompositeDataSource compositeDataSource1 = new
                  CompositeDataSource(ageDataSource, C3DataSource);
                CompositeDataSource compositeDataSource2 = new
                  CompositeDataSource(ageDataSource, C5DataSource);
                CompositeDataSource compositeDataSource3 = new
                  CompositeDataSource(ageDataSource, C10DataSource);
                CompositeDataSource compositeDataSource4 = new
                  CompositeDataSource(ageDataSource, C15DataSource);
                CompositeDataSource compositeDataSource5 = new
                  CompositeDataSource(ageDataSource, C25DataSource);
                CompositeDataSource compositeDataSource6 = new
                  CompositeDataSource(ageDataSource, C50DataSource);
                CompositeDataSource compositeDataSource7 = new
                  CompositeDataSource(ageDataSource, C75DataSource);
                CompositeDataSource compositeDataSource8 = new
                  CompositeDataSource(ageDataSource, C85DataSource);
                CompositeDataSource compositeDataSource9 = new
                  CompositeDataSource(ageDataSource, C90DataSource);
                CompositeDataSource compositeDataSource10 = new
                  CompositeDataSource(ageDataSource, C95DataSource);
                CompositeDataSource compositeDataSource11 = new
                  CompositeDataSource(ageDataSource, C97DataSource);
                CompositeDataSource compositeDataSource12 = new
                  CompositeDataSource(ageDataSource, C99DataSource);

                CompositeDataSource compositeDataSourceMeasurement = new
                  CompositeDataSource(ageMeasurementDataSource, measureDataSource);

                if (Convert.ToInt32(config.ThickP1) > 0 && C99[1] > 0)
                {
                    plotter.AddLineGraph(compositeDataSource12,
                        new Pen(new SolidColorBrush(GetColorFromConfig(config.ColorP1)), Convert.ToInt32(config.ThickP1)),
                        new PenDescription("99th Percentile"));
                }

                if (Convert.ToInt32(config.ThickP3) > 0 && C97[1] > 0)
                {
                    plotter.AddLineGraph(compositeDataSource11,
                      new Pen(new SolidColorBrush(GetColorFromConfig(config.ColorP3)), Convert.ToInt32(config.ThickP3)),
                      new PenDescription("97th Percentile"));
                }

                if (Convert.ToInt32(config.ThickP5) > 0 && C95[1] > 0)
                {
                    plotter.AddLineGraph(compositeDataSource10,
                      new Pen(new SolidColorBrush(GetColorFromConfig(config.ColorP5)), Convert.ToInt32(config.ThickP5)),
                      new PenDescription("95th Percentile"));
                }

                if (Convert.ToInt32(config.ThickP10) > 0 && C90[1] > 0)
                {
                    plotter.AddLineGraph(compositeDataSource9,
                      new Pen(new SolidColorBrush(GetColorFromConfig(config.ColorP10)), Convert.ToInt32(config.ThickP10)),
                      new PenDescription("90th Percentile"));
                }

                if (Convert.ToInt32(config.ThickP85) > 0 && C85[1] > 0)
                {
                    plotter.AddLineGraph(compositeDataSource8,
                      new Pen(new SolidColorBrush(GetColorFromConfig(config.ColorP85)), Convert.ToInt32(config.ThickP85)),
                      new PenDescription("85th Percentile"));
                }

                if (Convert.ToInt32(config.ThickP25) > 0 && C75[1] > 0)
                {
                    plotter.AddLineGraph(compositeDataSource7,
                      new Pen(new SolidColorBrush(GetColorFromConfig(config.ColorP25)), Convert.ToInt32(config.ThickP25)),
                      new PenDescription("75th Percentile"));
                }

                if (Convert.ToInt32(config.ThickP50) > 0 && C50[1] > 0)
                {
                    plotter.AddLineGraph(compositeDataSource6,
                      new Pen(new SolidColorBrush(GetColorFromConfig(config.ColorP50)), Convert.ToInt32(config.ThickP50)),
                      new PenDescription("50th Percentile"));
                }

                if (Convert.ToInt32(config.ThickP25) > 0 && C25[1] > 0)
                {
                    plotter.AddLineGraph(compositeDataSource5,
                      new Pen(new SolidColorBrush(GetColorFromConfig(config.ColorP25)), Convert.ToInt32(config.ThickP25)),
                      new PenDescription("25th Percentile"));
                }

                if (Convert.ToInt32(config.ThickP85) > 0 && C15[1] > 0)
                {
                    plotter.AddLineGraph(compositeDataSource4,
                      new Pen(new SolidColorBrush(GetColorFromConfig(config.ColorP85)), Convert.ToInt32(config.ThickP85)),
                      new PenDescription("15th Percentile"));
                }

                if (Convert.ToInt32(config.ThickP10) > 0 && C10[1] > 0)
                {
                    plotter.AddLineGraph(compositeDataSource3,
                      new Pen(new SolidColorBrush(GetColorFromConfig(config.ColorP10)), Convert.ToInt32(config.ThickP10)),
                      new PenDescription("10th Percentile"));
                }

                if (Convert.ToInt32(config.ThickP5) > 0 && C5[1] > 0)
                {
                    plotter.AddLineGraph(compositeDataSource2,
                      new Pen(new SolidColorBrush(GetColorFromConfig(config.ColorP5)), Convert.ToInt32(config.ThickP5)),
                      new PenDescription("5th Percentile"));
                }

                if (Convert.ToInt32(config.ThickP3) > 0 && C3[1] > 0)
                {
                    plotter.AddLineGraph(compositeDataSource1,
                      new Pen(new SolidColorBrush(GetColorFromConfig(config.ColorP3)), Convert.ToInt32(config.ThickP3)),
                      new PenDescription("3rd Percentile"));
                }

                if (Convert.ToInt32(config.ThickP1) > 0 && C1[1] > 0)
                {
                    plotter.AddLineGraph(compositeDataSource0,
                  new Pen(new SolidColorBrush(GetColorFromConfig(config.ColorP1)), Convert.ToInt32(config.ThickP1)),
                  new PenDescription("1st Percentile"));
                }
                
                Pen patientPen = new Pen(new SolidColorBrush(GetColorFromConfig(config.ColorPatientCurve)), Convert.ToInt32(config.ThickPatientCurve));
                patientPen.DashStyle = DashStyles.Dash;                                

                if (!config.TransparentDataPoints)
                {
                    plotter.AddLineGraph(compositeDataSourceMeasurement,
                        patientPen,
                        new CirclePointMarker
                        {
                            Size = Convert.ToDouble(config.PatientDataPointSize),
                            Pen = new Pen(new SolidColorBrush(GetColorFromConfig(config.ColorPatientDataPointBorder)), Convert.ToDouble(config.ThickPatientDataPointBorder)),
                            Fill = new SolidColorBrush(GetColorFromConfig(config.ColorPatientDataPointFill))
                        },
                        new PenDescription(PatientName));
                }
                else
                {
                    plotter.AddLineGraph(compositeDataSourceMeasurement,
                        patientPen,
                        new CirclePointMarker
                        {
                            Size = Convert.ToDouble(config.PatientDataPointSize),
                            Pen = new Pen(new SolidColorBrush(GetColorFromConfig(config.ColorPatientDataPointBorder)), Convert.ToDouble(config.ThickPatientDataPointBorder)),
                            Fill = Brushes.Transparent
                        },
                        new PenDescription(PatientName));
                }

                if (config.ShowDataPointLabels)
                {
                    ///////////////////////////////                
                    for (int i = 0; i < age.Count; i++)
                    {
                        List<double> ageLabel = new List<double>();
                        List<double> measureLabel = new List<double>();
                        string percentile = String.Format("{0:0.00}", score[i]);

                        ageLabel.Add(age[i]);
                        measureLabel.Add(measure[i]);

                        var ageMeasurementDataSourceLabel = new EnumerableDataSource<double>(ageLabel);
                        ageMeasurementDataSourceLabel.SetXMapping(x => x);

                        var measureDataSourceLabel = new EnumerableDataSource<double>(measureLabel);
                        measureDataSourceLabel.SetYMapping(y => y);

                        ds.Add(new CompositeDataSource(ageMeasurementDataSourceLabel, measureDataSourceLabel));

                        chart.Add(plotter.AddLineGraph(ds[i],
                            null,
                            new CenteredTextMarker
                            {
                                Text = " " + percentile + " "
                            },
                            new PenDescription(score[i].ToString())));
                    }
                    ////////////////////////////////
                }

                //chart.MarkerGraph.DataSource = null;

                xAxis.ShowMinorTicks = true;
                yAxis.ShowMinorTicks = true;
                plotter.AxisGrid.DrawVerticalMinorTicks = false;
                plotter.AxisGrid.DrawHorizontalMinorTicks = false;
                plotter.Legend.LegendLeft = 45;
                plotter.Legend.LegendRight = Double.NaN;

                if (!config.ShowLegend)
                {
                    plotter.Legend.Visibility = Visibility.Hidden;
                }
                else
                {
                    plotter.Legend.Visibility = Visibility.Visible;
                }

                if (config.ShowCoordinateCursor)
                {
                    plotter.Children.Add(new CursorCoordinateGraph());
                }
                plotter.Viewport.FitToView();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        private void PlotZScores(List<double> score, List<double> age)
        {
            try
            {
                // Set window title
                this.Title = Reference + " " + Measurement + " " + Type;

                // Set file name to pull growth curves from
                string fileName = "..\\..\\..\\" + Reference + Measurement + "_" + Gender + ".csv";

                // load growth curves from the appropriate file
                List<GrowthCurvesZScores> scoresList = LoadGrowthCurvesZScores(fileName);

                double[] SD3neg = new double[scoresList.Count];
                double[] SD2neg = new double[scoresList.Count];
                double[] SD1neg = new double[scoresList.Count];
                double[] SD0 = new double[scoresList.Count];
                double[] SD1pos = new double[scoresList.Count];
                double[] SD2pos = new double[scoresList.Count];
                double[] SD3pos = new double[scoresList.Count];
                double[] ages = new double[scoresList.Count];

                for (int i = 0; i < scoresList.Count; ++i)
                {
                    SD3neg[i] = scoresList[i].SD3neg;
                    SD2neg[i] = scoresList[i].SD2neg;
                    SD1neg[i] = scoresList[i].SD1neg;
                    SD0[i] = scoresList[i].SD0;
                    SD1pos[i] = scoresList[i].SD1pos;
                    SD2pos[i] = scoresList[i].SD2pos;
                    SD3pos[i] = scoresList[i].SD3pos;
                    ages[i] = scoresList[i].xaxis;
                }

                var SD3negDataSource = new EnumerableDataSource<double>(SD3neg);
                SD3negDataSource.SetYMapping(y => y);

                var SD2negDataSource = new EnumerableDataSource<double>(SD2neg);
                SD2negDataSource.SetYMapping(y => y);

                var SD1negDataSource = new EnumerableDataSource<double>(SD1neg);
                SD1negDataSource.SetYMapping(y => y);

                var SD0DataSource = new EnumerableDataSource<double>(SD0);
                SD0DataSource.SetYMapping(y => y);

                var SD1posDataSource = new EnumerableDataSource<double>(SD1pos);
                SD1posDataSource.SetYMapping(y => y);

                var SD2posDataSource = new EnumerableDataSource<double>(SD2pos);
                SD2posDataSource.SetYMapping(y => y);

                var SD3posDataSource = new EnumerableDataSource<double>(SD3pos);
                SD3posDataSource.SetYMapping(y => y);

                var ageDataSource = new EnumerableDataSource<double>(ages);
                ageDataSource.SetXMapping(x => x);

                var ageMeasurementDataSource = new EnumerableDataSource<double>(age);
                ageMeasurementDataSource.SetXMapping(x => x);

                var scoreDataSource = new EnumerableDataSource<double>(score);
                scoreDataSource.SetYMapping(y => y);

                CompositeDataSource compositeDataSource1 = new
                  CompositeDataSource(ageDataSource, SD3negDataSource);
                CompositeDataSource compositeDataSource2 = new
                  CompositeDataSource(ageDataSource, SD2negDataSource);
                CompositeDataSource compositeDataSource3 = new
                  CompositeDataSource(ageDataSource, SD1negDataSource);
                CompositeDataSource compositeDataSource4 = new
                  CompositeDataSource(ageDataSource, SD0DataSource);
                CompositeDataSource compositeDataSource5 = new
                  CompositeDataSource(ageDataSource, SD1posDataSource);
                CompositeDataSource compositeDataSource6 = new
                  CompositeDataSource(ageDataSource, SD2posDataSource);
                CompositeDataSource compositeDataSource7 = new
                  CompositeDataSource(ageDataSource, SD3posDataSource);

                CompositeDataSource compositeDataSourceMeasurement = new
                  CompositeDataSource(ageMeasurementDataSource, scoreDataSource);

                plotter.AddLineGraph(compositeDataSource1,
                  new Pen(Brushes.Red, 1),
                  new PenDescription("SD -3"));

                plotter.AddLineGraph(compositeDataSource2,
                  new Pen(Brushes.Orange, 1),
                  new PenDescription("SD -2"));

                plotter.AddLineGraph(compositeDataSource3,
                  new Pen(Brushes.Violet, 1),
                  new PenDescription("SD -1"));

                plotter.AddLineGraph(compositeDataSource4,
                  new Pen(Brushes.Green, 1),
                  new PenDescription("SD 0"));

                plotter.AddLineGraph(compositeDataSource5,
                  new Pen(Brushes.Blue, 2),
                  new PenDescription("SD +1"));

                plotter.AddLineGraph(compositeDataSource6,
                  new Pen(Brushes.Green, 1),
                  new PenDescription("SD +2"));

                plotter.AddLineGraph(compositeDataSource7,
                  new Pen(Brushes.Brown, 1),
                  new PenDescription("SD +3"));

                plotter.AddLineGraph(compositeDataSourceMeasurement,
                    null/*new Pen(Brushes.Transparent, 1)*/,
                    new CirclePointMarker
                    {
                        Size = 8.0,
                        Pen = new Pen(Brushes.Black, 1.0),
                        Fill = Brushes.Red
                    },
                    new PenDescription(PatientName));

                plotter.Legend.LegendLeft = 10;
                plotter.Legend.LegendRight = Double.NaN;
                plotter.Viewport.FitToView();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }
/*
        private void PlotNormalCurve(List<double> score, List<double> age)
        {
            try
            {

                // Set file name to pull growth curves from
                string fileName = "Resources\\" + Reference + Measurement + "_" + Gender + ".csv";

                // load growth curves from the appropriate file
                List<GrowthCurvesPercentiles> percentilesList = LoadGrowthCurvesPercentiles(fileName, Measurement, Metric);

                double[] C3 = new double[percentilesList.Count];
                double[] C5 = new double[percentilesList.Count];
                double[] C10 = new double[percentilesList.Count];
                double[] C25 = new double[percentilesList.Count];
                double[] C50 = new double[percentilesList.Count];
                double[] C75 = new double[percentilesList.Count];
                double[] C85 = new double[percentilesList.Count];
                double[] C90 = new double[percentilesList.Count];
                double[] C95 = new double[percentilesList.Count];
                double[] C97 = new double[percentilesList.Count];
                double[] ages = new double[percentilesList.Count];

                for (int i = 0; i < percentilesList.Count; ++i)
                {
                    C3[i] = percentilesList[i].C3;
                    C5[i] = percentilesList[i].C5;
                    C10[i] = percentilesList[i].C10;
                    C25[i] = percentilesList[i].C25;
                    C50[i] = percentilesList[i].C50;
                    C75[i] = percentilesList[i].C75;
                    C85[i] = percentilesList[i].C85;
                    C90[i] = percentilesList[i].C90;
                    C95[i] = percentilesList[i].C95;
                    C97[i] = percentilesList[i].C97;
                    ages[i] = percentilesList[i].xaxis;
                }

                var C3DataSource = new EnumerableDataSource<double>(C3);
                C3DataSource.SetYMapping(y => y);

                var C5DataSource = new EnumerableDataSource<double>(C5);
                C5DataSource.SetYMapping(y => y);

                var C10DataSource = new EnumerableDataSource<double>(C10);
                C10DataSource.SetYMapping(y => y);

                var C25DataSource = new EnumerableDataSource<double>(C25);
                C25DataSource.SetYMapping(y => y);

                var C50DataSource = new EnumerableDataSource<double>(C50);
                C50DataSource.SetYMapping(y => y);

                var C75DataSource = new EnumerableDataSource<double>(C75);
                C75DataSource.SetYMapping(y => y);

                var C85DataSource = new EnumerableDataSource<double>(C85);
                C85DataSource.SetYMapping(y => y);

                var C90DataSource = new EnumerableDataSource<double>(C90);
                C90DataSource.SetYMapping(y => y);

                var C95DataSource = new EnumerableDataSource<double>(C95);
                C95DataSource.SetYMapping(y => y);

                var C97DataSource = new EnumerableDataSource<double>(C97);
                C97DataSource.SetYMapping(y => y);

                var ageDataSource = new EnumerableDataSource<double>(ages);
                ageDataSource.SetXMapping(x => x);

                var ageMeasurementDataSource = new EnumerableDataSource<double>(age);
                ageMeasurementDataSource.SetXMapping(x => x);

                var scoreDataSource = new EnumerableDataSource<double>(score);
                scoreDataSource.SetYMapping(y => y);

                CompositeDataSource compositeDataSource1 = new
                  CompositeDataSource(ageDataSource, C3DataSource);
                CompositeDataSource compositeDataSource2 = new
                  CompositeDataSource(ageDataSource, C5DataSource);
                CompositeDataSource compositeDataSource3 = new
                  CompositeDataSource(ageDataSource, C10DataSource);
                CompositeDataSource compositeDataSource4 = new
                  CompositeDataSource(ageDataSource, C25DataSource);
                CompositeDataSource compositeDataSource5 = new
                  CompositeDataSource(ageDataSource, C50DataSource);
                CompositeDataSource compositeDataSource6 = new
                  CompositeDataSource(ageDataSource, C75DataSource);
                CompositeDataSource compositeDataSource7 = new
                  CompositeDataSource(ageDataSource, C85DataSource);
                CompositeDataSource compositeDataSource8 = new
                  CompositeDataSource(ageDataSource, C90DataSource);
                CompositeDataSource compositeDataSource9 = new
                  CompositeDataSource(ageDataSource, C95DataSource);
                CompositeDataSource compositeDataSource10 = new
                  CompositeDataSource(ageDataSource, C97DataSource);

                CompositeDataSource compositeDataSourceMeasurement = new
                  CompositeDataSource(ageMeasurementDataSource, scoreDataSource);

                plotter.AddLineGraph(compositeDataSource10,
                  new Pen(Brushes.Red, 1),
                  new PenDescription("97th Percentile"));

                plotter.AddLineGraph(compositeDataSource9,
                  new Pen(Brushes.Orange, 1),
                  new PenDescription("95th Percentile"));

                plotter.AddLineGraph(compositeDataSource8,
                  new Pen(Brushes.Violet, 1),
                  new PenDescription("90th Percentile"));

                if (Measurement.Equals("BMI"))
                {
                    plotter.AddLineGraph(compositeDataSource7,
                      new Pen(Brushes.Brown, 1),
                      new PenDescription("85th Percentile"));
                }

                plotter.AddLineGraph(compositeDataSource6,
                  new Pen(Brushes.Green, 1),
                  new PenDescription("75th Percentile"));

                plotter.AddLineGraph(compositeDataSource5,
                  new Pen(Brushes.Blue, 2),
                  new PenDescription("50th Percentile"));

                plotter.AddLineGraph(compositeDataSource4,
                  new Pen(Brushes.Green, 1),
                  new PenDescription("25th Percentile"));

                plotter.AddLineGraph(compositeDataSource3,
                  new Pen(Brushes.Violet, 1),
                  new PenDescription("10th Percentile"));

                plotter.AddLineGraph(compositeDataSource2,
                  new Pen(Brushes.Orange, 1),
                  new PenDescription("5th Percentile"));

                plotter.AddLineGraph(compositeDataSource1,
                  new Pen(Brushes.Red, 1),
                  new PenDescription("3rd Percentile"));

                plotter.AddLineGraph(compositeDataSourceMeasurement,
                    null, //new Pen(Brushes.Transparent, 1),
                    new CirclePointMarker
                    {
                        Size = 8.0,
                        Pen = new Pen(Brushes.Black, 1.0),
                        Fill = Brushes.Red
                    },
                    new PenDescription(PatientName));

                plotter.Legend.LegendLeft = 10;
                plotter.Legend.LegendRight = Double.NaN;
                plotter.Viewport.FitToView();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }
        */
        private static List<GrowthCurvesPercentiles> LoadGrowthCurvesPercentiles(string fileName, string measurement, bool metric)
        {
            var result = new List<GrowthCurvesPercentiles>();
            FileStream fs = new FileStream(fileName, FileMode.Open);
            StreamReader sr = new StreamReader(fs);

            double xAxisModifier = 1;
            double yAxisModifier = 1;

            if (!metric)
            {
                if (measurement.Equals(MeasurementOptions.BMI.Abbreviation))
                {
                }
                else if (measurement.Equals(MeasurementOptions.HA.Abbreviation))
                {
                    yAxisModifier = MeasurementUnits.Centimeter.ToInches();
                }
                else if (measurement.Equals(MeasurementOptions.HCA.Abbreviation))
                {
                    yAxisModifier = MeasurementUnits.Centimeter.ToInches();
                }
                else if (measurement.Equals(MeasurementOptions.LA.Abbreviation))
                {
                    yAxisModifier = MeasurementUnits.Centimeter.ToInches();
                }
                else if (measurement.Equals(MeasurementOptions.MUACA.Abbreviation))
                {
                    yAxisModifier = MeasurementUnits.Centimeter.ToInches();
                }
                else if (measurement.Equals(MeasurementOptions.SSFA.Abbreviation))
                {
                    yAxisModifier = MeasurementUnits.Millimeter.ToInches();
                }
                else if (measurement.Equals(MeasurementOptions.TSFA.Abbreviation))
                {
                    yAxisModifier = MeasurementUnits.Millimeter.ToInches();
                }
                else if (measurement.Equals(MeasurementOptions.WA.Abbreviation))
                {
                    yAxisModifier = MeasurementUnits.Kilogram.ToPounds();
                }
                else if (measurement.Equals(MeasurementOptions.WH.Abbreviation))
                {
                    yAxisModifier = MeasurementUnits.Kilogram.ToPounds();
                    xAxisModifier = MeasurementUnits.Centimeter.ToInches();
                }
                else if (measurement.Equals(MeasurementOptions.WL.Abbreviation))
                {
                    yAxisModifier = MeasurementUnits.Kilogram.ToPounds();
                    xAxisModifier = MeasurementUnits.Centimeter.ToInches();
                }
            }
            
            string line = "";
            line = sr.ReadLine();
            string[] pieces = line.Split(',');            
            string[] percentiles = pieces;
            if (pieces[0].Equals("Age") || pieces[0].Equals("Month") || pieces[0].Equals("Height") || pieces[0].Equals("Length"))
            {
                while ((line = sr.ReadLine()) != null)
                {
                    pieces = line.Split(',');                                    
                    double age = xAxisModifier * double.Parse(pieces[0]);                    
                    double c1 = 0;
                    double c3 = 0;
                    double c5 = 0;
                    double c10 = 0;
                    double c15 = 0;
                    double c25 = 0;
                    double c50 = 0;
                    double c75 = 0;
                    double c85 = 0;
                    double c90 = 0;
                    double c95 = 0;
                    double c97 = 0;
                    double c99 = 0;

                    for (int i = 0; i < percentiles.Length; i++)
                    {
                        if(percentiles[i].Equals("P1"))
                        {
                            c1 = yAxisModifier * double.Parse(pieces[i]);
                        }

                        if (percentiles[i].Equals("P3"))
                        {
                            c3 = yAxisModifier * double.Parse(pieces[i]);
                        }

                        if (percentiles[i].Equals("P5"))
                        {
                            c5 = yAxisModifier * double.Parse(pieces[i]);
                        }

                        if (percentiles[i].Equals("P10"))
                        {
                            c10 = yAxisModifier * double.Parse(pieces[i]);
                        }

                        if (percentiles[i].Equals("P15"))
                        {
                            c15 = yAxisModifier * double.Parse(pieces[i]);
                        }

                        if (percentiles[i].Equals("P25"))
                        {
                            c25 = yAxisModifier * double.Parse(pieces[i]);
                        }

                        if (percentiles[i].Equals("P50"))
                        {
                            c50 = yAxisModifier * double.Parse(pieces[i]);                            
                        }

                        if (percentiles[i].Equals("P75"))
                        {
                            c75 = yAxisModifier * double.Parse(pieces[i]);
                        }

                        if (percentiles[i].Equals("P85"))
                        {
                            c85 = yAxisModifier * double.Parse(pieces[i]);
                        }
                        if (percentiles[i].Equals("P90"))
                        {
                            c90 = yAxisModifier * double.Parse(pieces[i]);
                        }

                        if (percentiles[i].Equals("P95"))
                        {
                            c95 = yAxisModifier * double.Parse(pieces[i]);
                        }

                        if (percentiles[i].Equals("P97"))
                        {
                            c97 = yAxisModifier * double.Parse(pieces[i]);
                        }

                        if (percentiles[i].Equals("P99"))
                        {
                            c99 = yAxisModifier * double.Parse(pieces[i]);
                        }
                    }
                    GrowthCurvesPercentiles growthCurves = new GrowthCurvesPercentiles(c1, c3, c5, c10, c15, c25, c50, c75,
                        c85, c90, c95, c97, c99, age);
                    result.Add(growthCurves);
                }
            }
            // include 85th percentile
            else if (pieces.Length == 11)
            {
                    double age = xAxisModifier * double.Parse(pieces[0]);
                    double c3 = yAxisModifier * double.Parse(pieces[1]);
                    double c5 = yAxisModifier * double.Parse(pieces[2]);
                    double c10 = yAxisModifier * double.Parse(pieces[3]);
                    double c25 = yAxisModifier * double.Parse(pieces[4]);
                    double c50 = yAxisModifier * double.Parse(pieces[5]);
                    double c75 = yAxisModifier * double.Parse(pieces[6]);
                    double c85 = yAxisModifier * double.Parse(pieces[7]);
                    double c90 = yAxisModifier * double.Parse(pieces[8]);
                    double c95 = yAxisModifier * double.Parse(pieces[9]);
                    double c97 = yAxisModifier * double.Parse(pieces[10]);
                    
                    GrowthCurvesPercentiles growthCurves = new GrowthCurvesPercentiles(c3, c5, c10, c25, c50, c75,
                        c85, c90, c95, c97, age);
                    result.Add(growthCurves);
            }
            else if (pieces.Length == 10)
            {
                    double age = xAxisModifier * double.Parse(pieces[0]);
                    double c3 = yAxisModifier * double.Parse(pieces[1]);
                    double c5 = yAxisModifier * double.Parse(pieces[2]);
                    double c10 = yAxisModifier * double.Parse(pieces[3]);
                    double c25 = yAxisModifier * double.Parse(pieces[4]);
                    double c50 = yAxisModifier * double.Parse(pieces[5]);
                    double c75 = yAxisModifier * double.Parse(pieces[6]);
                    double c90 = yAxisModifier * double.Parse(pieces[7]);
                    double c95 = yAxisModifier * double.Parse(pieces[8]);
                    double c97 = yAxisModifier * double.Parse(pieces[9]);
                    
                    GrowthCurvesPercentiles growthCurves = new GrowthCurvesPercentiles(c3, c5, c10, c25, c50, c75,
                        c90, c95, c97, age);
                    result.Add(growthCurves);
            }            
            sr.Close();
            fs.Close();
            return result;
        }

        private static List<GrowthCurvesZScores> LoadGrowthCurvesZScores(string fileName)
        {
            var result = new List<GrowthCurvesZScores>();
            FileStream fs = new FileStream(fileName, FileMode.Open);
            StreamReader sr = new StreamReader(fs);

            string line = "";
            while ((line = sr.ReadLine()) != null)
            {
                string[] pieces = line.Split(',');
                double age = double.Parse(pieces[0]);
                double sd3neg = double.Parse(pieces[1]);
                double sd2neg = double.Parse(pieces[2]);
                double sd1neg = double.Parse(pieces[3]);
                double sd0 = double.Parse(pieces[4]);
                double sd1pos = double.Parse(pieces[5]);
                double sd2pos = double.Parse(pieces[6]);
                double sd3pos = double.Parse(pieces[7]);
                GrowthCurvesZScores growthCurves = new GrowthCurvesZScores(sd3neg, sd2neg, sd1neg, sd0, sd1pos, sd2pos, sd3pos, age);
                result.Add(growthCurves);
            }
            sr.Close();
            fs.Close();
            return result;
        }
        #endregion Methods

        public class GrowthCurvesPercentiles
        {
            public double C1;
            public double C3;
            public double C5;
            public double C10;
            public double C15;
            public double C25;
            public double C50;
            public double C75;
            public double C85;
            public double C90;
            public double C95;
            public double C97;
            public double C99;
            public double xaxis;

            public GrowthCurvesPercentiles(double C3, double C5, double C10, double C25, double C50, double C75, double C85,
                double C90, double C95, double C97, double xaxis)
            {
                this.C3 = C3;
                this.C5 = C5;
                this.C10 = C10;
                this.C25 = C25;
                this.C50 = C50;
                this.C75 = C75;
                this.C85 = C85;
                this.C90 = C90;
                this.C95 = C95;
                this.C97 = C97;
                this.xaxis = xaxis;
            }

            public GrowthCurvesPercentiles(double C3, double C5, double C10, double C25, double C50, double C75, double C90, 
                double C95, double C97, double xaxis)
            {
                this.C3 = C3;
                this.C5 = C5;
                this.C10 = C10;
                this.C25 = C25;
                this.C50 = C50;
                this.C75 = C75;                
                this.C90 = C90;
                this.C95 = C95;
                this.C97 = C97;
                this.xaxis = xaxis;
            }

            public GrowthCurvesPercentiles(double C1, double C3, double C5, double C10, double C15, double C25, double C50, double C75, double C85, double C90,
                double C95, double C97, double C99, double xaxis)
            {
                this.C1 = C1;
                this.C3 = C3;
                this.C5 = C5;
                this.C10 = C10;
                this.C15 = C15;
                this.C25 = C25;
                this.C50 = C50;
                this.C75 = C75;
                this.C85 = C85;
                this.C90 = C90;
                this.C95 = C95;
                this.C97 = C97;
                this.C99 = C99;
                this.xaxis = xaxis;
            }
        }

        public class GrowthCurvesZScores
        {
            public double SD3neg;
            public double SD2neg;
            public double SD1neg;
            public double SD0;
            public double SD1pos;
            public double SD2pos;
            public double SD3pos;

            public double xaxis;

            public GrowthCurvesZScores(double SD3neg, double SD2neg, double SD1neg, double SD0, double SD1pos, double SD2pos, double SD3pos, double xaxis)
            {
                this.SD3neg = SD3neg;
                this.SD2neg = SD2neg;
                this.SD1neg = SD1neg;
                this.SD0 = SD0;
                this.SD1pos = SD1pos;
                this.SD2pos = SD2pos;
                this.SD3pos = SD3pos;
                this.xaxis = xaxis;
            }
        }
    }
}
